package com.zhumo.sz.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.zhumo.sz.common.CommonInsert;
import com.zhumo.sz.common.CustomLogServerConfig;
import com.zhumo.sz.common.http.HttpClientHelper;
import com.zhumo.sz.common.utils.DateFormatUtil;
import com.zhumo.sz.common.utils.GeographyUtil;
import com.zhumo.sz.config.AddressConfig;
import com.zhumo.sz.entity.area.BaseArea;
import com.zhumo.sz.entity.bike.SharedBikeEnterprise;
import com.zhumo.sz.entity.bike.SharedBikeOrderDetail;
import com.zhumo.sz.entity.user.UserInfo;
import com.zhumo.sz.gaode.*;
import com.zhumo.sz.mapper.BikeMapper;
import com.zhumo.sz.mapper.PublicMapper;
import com.zhumo.sz.mapper.UserMapper;
import com.zhumo.sz.mock.RandomGenerator;
import com.zhumo.sz.mock.TrafficMocker;
import com.zhumo.sz.service.SharedBikeService;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.HttpClient;
import org.apache.http.entity.ContentType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.*;


/**
 * @author jiaqi.zhu
 * @comment 共享单车服务层 包含 共享单车企业信息 和 每日共享单车订单
 */

@Slf4j
@Service
public class SharedBikeServiceImpl implements SharedBikeService {

    @Autowired
    private BikeMapper bikeMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private PublicMapper publicMapper;

    private static GaoDeAddressProcessor gaoDeAddressProcessor;


    /**
     * 获取共享单车订单信息
     * @return
     */
    @Override
    public CommonInsert<SharedBikeOrderDetail> setBikeOrder(int num,String startDate,String endDate,String type) {
        //首先计算lock时间
        if(Objects.isNull(type) || (! ("batch").equals(type) && ! ("realtime").equals(type))){
            throw new IllegalArgumentException("The generation type parameter passing is illegal ");
        }
        String url = "https://opendata.sz.gov.cn/api/29200_00403627/1/service.xhtml";
        HttpClient client = HttpClientHelper.createDefault();
        HashMap<String, Object> bikeOrderParamMap = new HashMap<>();
        bikeOrderParamMap.put("appKey", CustomLogServerConfig.OPENDATA_SZ_APP_KEY);
        bikeOrderParamMap.put("page",1);
        bikeOrderParamMap.put("rows",num);
        bikeOrderParamMap.put("startDate",startDate);
        bikeOrderParamMap.put("endDate",endDate);
        JSONObject transferResponse = HttpClientHelper.sendJsonGetRequest(url, AddressConfig.ContentTypeJsonHeader, bikeOrderParamMap,
                ContentType.APPLICATION_JSON, client);
        /*
        {"date":"","total":3502,
        "data":[{"START_TIME":"2021-01-01 00:01:27.0","START_LAT":"22.62814375","END_TIME":"2021-01-01 00:15:38.0",
        "END_LNG":"114.06562277","USER_ID":"73711ce41c58c075086daa**********","START_LNG":"114.06564833","END_LAT":"22.62775668","COM_ID":""},
        {"START_TIME":"2021-01-01 00:01:27.0","START_LAT":"22.62823155",
        "END_TIME":"2021-01-01 00:15:38.0","END_LNG":"114.06571057","USER_ID":"0e99e106c42682a8434a38**********",
        "START_LNG":"114.06573613","END_LAT":"22.62784448","COM_ID":""}],"page":1,"rows":2}
         */
        String rows = transferResponse.getString("rows");
        if (! String.valueOf(num).equals(rows)) {
            throw new RuntimeException("The number of requests does not match the return result");
        }
        List<UserInfo> userList = userMapper.selectAllUser();
        HashSet<UserInfo> existedUserSet  = new HashSet<>();
        HashSet<String> orderSet = new HashSet<>();
        //查询所有地理位置
        List<BaseArea> baseAreaList = publicMapper.getAllArea();
        HashSet<Long> bikeSet = new HashSet<>(); //自行车id
        ArrayList<SharedBikeOrderDetail> shardBikeOrderCollect = new ArrayList<>();
        JSONArray data = transferResponse.getJSONArray("data");
        data.forEach( dataJs -> {
            SharedBikeOrderDetail sharedBikeOrderDetail = new SharedBikeOrderDetail();
            //定义用户
            while (true){
                UserInfo userInfo = userList.get(new Random().nextInt(userList.size()));
                if (! existedUserSet.contains(userInfo)){
                    sharedBikeOrderDetail.setUserId(userInfo.getUserId());
                    existedUserSet.add(userInfo);
                    break;
                }
            }
            //定义订单 每日订单增加时间前缀 避免重复
            while(true){
                String orderNum = RandomGenerator.generateRandomNumber(12);
                if (! orderSet.contains(orderNum)){
                    String orderId = startDate.replaceAll("-","").replaceAll(":","")
                            .substring(0,4) + orderNum;
                    sharedBikeOrderDetail.setOrderId(orderId);
                    orderSet.add(orderId);
                    break;
                }
            }
            //bike id
            while (true){
                long bikeId = Long.parseLong(RandomGenerator.generateRandomNumber(8));
                if (! bikeSet.contains(bikeId)){
                    bikeSet.add(bikeId);
                    sharedBikeOrderDetail.setBikeId(bikeId);
                    break;
                }
            }
            //解析经纬度 计算距离与Poi
            JSONObject bikeOrderJsonObj = JSONObject.parseObject(JSON.toJSONString(dataJs));
            double startLat = Double.parseDouble(bikeOrderJsonObj.getString("START_LAT"));
            sharedBikeOrderDetail.setStartLat(startLat);
            double startLng = Double.parseDouble(bikeOrderJsonObj.getString("START_LNG"));
            sharedBikeOrderDetail.setStartLng(startLng);
            double endLat = Double.parseDouble(bikeOrderJsonObj.getString("END_LAT"));
            double endLng = Double.parseDouble(bikeOrderJsonObj.getString("END_LNG"));
            sharedBikeOrderDetail.setEndLat(endLat);
            sharedBikeOrderDetail.setEndLng(endLng);
            gaoDeAddressProcessor = GaoDeAddressProcessor.init(gaoDeAddressProcessor);
            //解析star poi
            GaoDeResGeoArea startGaoDeResGeoArea = gaoDeAddressProcessor
                    .processReverseCode(String.valueOf(startLng) + "," + String.valueOf(startLat)
                            , "all", "100", GaoDeAddressProcessor.PUBLIC_POI_TYPE, "1", "JSON");
            HashMap<String, ArrayList<Poi>> startPoiMap = PoiParser.parseGaodeResponse(JSONArray.parseArray(startGaoDeResGeoArea.getPois()));
            FirstPoi<String> startPoi = PoiParser.filePoi(startPoiMap, FirstPoi.class); //Poi归档
            sharedBikeOrderDetail.setStartPoi(startPoi);
            //end poi
            GaoDeResGeoArea endGaoDeResGeoArea = gaoDeAddressProcessor
                    .processReverseCode(String.valueOf(endLng) + "," + String.valueOf(endLat)
                            , "all", "100", GaoDeAddressProcessor.PUBLIC_POI_TYPE, "1", "JSON");
            HashMap<String, ArrayList<Poi>> endPoiMap = PoiParser.parseGaodeResponse(JSONArray.parseArray(endGaoDeResGeoArea.getPois()));
            FirstPoi<String> endPoi = PoiParser.filePoi(endPoiMap, FirstPoi.class); //Poi归档
            sharedBikeOrderDetail.setEndPoi(endPoi);
            double distance = GeographyUtil.distanceByCoordinate(startLat,startLng,endLat,endLng) * 1.25 ;  // avg_bike_v = 21.5Km / H
            String year = startDate.replaceAll(":","").replaceAll("-","").substring(0,4);
            //时间修改 分批与实
            if (type.equals("batch")){
               sharedBikeOrderDetail.setLockTime(Timestamp.valueOf(year + bikeOrderJsonObj.getString("END_TIME").substring(4)));
               sharedBikeOrderDetail.setOpenTime(Timestamp.valueOf(year + bikeOrderJsonObj.getString("START_TIME").substring(4)));
            }
            if (type.equals("realtime")) {
                Timestamp lockTime = Timestamp.valueOf(DateFormatUtil.toYmdHms(System.currentTimeMillis()));
                sharedBikeOrderDetail.setLockTime(lockTime);   //推算时间
                long seconds = (long) Math.ceil(distance / (21.5 * 1000));
                sharedBikeOrderDetail.setOpenTime(Timestamp.valueOf(RandomGenerator.generateStartTime(lockTime.toString(), seconds)));
            }
            sharedBikeOrderDetail.setEndRoads(JSON.toJSONString(Road.parseRoadForMysql(endGaoDeResGeoArea.getRoads())));
            sharedBikeOrderDetail.setStartRoads(JSON.toJSONString(Road.parseRoadForMysql(startGaoDeResGeoArea.getRoads())));
            sharedBikeOrderDetail.setStartCity(startGaoDeResGeoArea.getCity());
//            sharedBikeOrderDetail.setStartCityCode(startGaoDeResGeoArea.getCityCode()); 废弃 使用国家统计局编码
            sharedBikeOrderDetail.setEndCity(endGaoDeResGeoArea.getCity());
//            sharedBikeOrderDetail.setEndCityCode(endGaoDeResGeoArea.getCityCode());
            sharedBikeOrderDetail.setStartDistrict(startGaoDeResGeoArea.getDistrict());
            sharedBikeOrderDetail.setEndDistrict(endGaoDeResGeoArea.getDistrict());
            sharedBikeOrderDetail.setStartTown(startGaoDeResGeoArea.getTown());
            sharedBikeOrderDetail.setEndTown(endGaoDeResGeoArea.getTown());
            //补充编码
            for (BaseArea baseArea : baseAreaList) {
                if (baseArea.getTown().equals(sharedBikeOrderDetail.getStartTown())){
                    sharedBikeOrderDetail.setStartTownCode(baseArea.getIpwebStreetCode());
                    sharedBikeOrderDetail.setStartDistrictCode(baseArea.getIpwebDistrictCode());
                    sharedBikeOrderDetail.setStartCityCode(baseArea.getIpwebCityCode());
                }
            }
            for (BaseArea baseArea : baseAreaList) {
                if (baseArea.getTown().equals(sharedBikeOrderDetail.getEndTown())){
                    sharedBikeOrderDetail.setEndTownCode(baseArea.getIpwebStreetCode());
                    sharedBikeOrderDetail.setEndDistrictCode(baseArea.getIpwebDistrictCode());
                    sharedBikeOrderDetail.setEndCityCode(baseArea.getIpwebCityCode());
                }
            }
            //支付状况  企业编码 1 滴滴  2 美团  3 阿里巴巴
            sharedBikeOrderDetail.setBikeComId(TrafficMocker.setCom());
            if (sharedBikeOrderDetail.getBikeComId().equals(1)){
                sharedBikeOrderDetail.setPaymentType("支付宝");
                sharedBikeOrderDetail.setScanCodeApp("哈喽单车");
                if (TrafficMocker.isBikeInActive()){
                    sharedBikeOrderDetail.setActivityCode(TrafficMocker.getAliPayActiveCode());
                }
            }else {
                sharedBikeOrderDetail.setPaymentType("微信");
                if (sharedBikeOrderDetail.getBikeComId().equals(2)){
                    sharedBikeOrderDetail.setScanCodeApp("美团出行");
                }else {
                    sharedBikeOrderDetail.setScanCodeApp("滴滴青桔");
                }
            }
            //支付金额 根据骑行时间
            long through = DateFormatUtil.getSecondsDifference(sharedBikeOrderDetail.getLockTime(), sharedBikeOrderDetail.getOpenTime());
            BigDecimal orderAmount = BigDecimal.valueOf(Math.ceil(through < 1800 ? 1 : through / 1800) * 2);
            sharedBikeOrderDetail.setOrderAmount(orderAmount);
            sharedBikeOrderDetail.setPaymentAmount(sharedBikeOrderDetail.getActivityCode() != null && sharedBikeOrderDetail.getActivityCode().equals(1) ?
                    orderAmount.subtract(BigDecimal.ONE) : orderAmount);
            sharedBikeOrderDetail.setActivityReductionAmount(sharedBikeOrderDetail.getActivityCode() != null && sharedBikeOrderDetail.getActivityCode().equals(1) ?
                    BigDecimal.ONE : BigDecimal.ZERO);
            //流水号
            sharedBikeOrderDetail.setSerialNumber(RandomGenerator.generateRandomString(13));
            sharedBikeOrderDetail.setPaymentTime(Timestamp.valueOf(RandomGenerator.generateStartTime(String.valueOf(sharedBikeOrderDetail.getLockTime()),-5)));
            sharedBikeOrderDetail.setCreateTime(sharedBikeOrderDetail.getLockTime());
            TrafficMocker.clearUnPaymentBikeOrder(sharedBikeOrderDetail);
            shardBikeOrderCollect.add(sharedBikeOrderDetail);
            log.info("写入单车订单: " + sharedBikeOrderDetail.getOrderId());
        });
        int result = bikeMapper.insertSubwayTraffic(shardBikeOrderCollect);
        return new CommonInsert<>(shardBikeOrderCollect.size(),result);
    }

    /**
     * 获取共享单车订单
     * @return················
     */
    @Override
    public CommonInsert<SharedBikeEnterprise> setBikeEnterprise() {
        return null;
    }

//    public static void main(String[] args) {
//        SharedBikeServiceImpl bikeService = new SharedBikeServiceImpl();
//        bikeService.setBikeOrder(2,"20210101","20210102","batch");
//    }
}
